home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 2 / Atari Mega Archive CD - Volume 2.iso / minix / up1510b.tgz / up1510b / src / commands / uniq.c < prev    next >
C/C++ Source or Header  |  1990-07-15  |  3KB  |  188 lines

  1. /* uniq - compact repeated lines        Author: John Woods */
  2. /* Uniq [-udc] [-n] [+n] [infile [outfile]]
  3.  *
  4.  *    Written 02/08/86 by John Woods, placed into public domain.  Enjoy.
  5.  *
  6.  */
  7.  
  8. /* If the symbol WRITE_ERROR is defined, uniq will exit(1) if it gets a
  9.  * write error on the output.  This is not (of course) how V7 uniq does it,
  10.  * so undefine the symbol if you want to lose your output to a full disk
  11.  */
  12.  
  13. #define WRITE_ERROR 1
  14. #define isdigit(c) (c >= '0' && c <= '9')
  15. #include <errno.h>
  16. #include <stdio.h>
  17.  
  18. FILE *fopen();
  19. char buffer[BUFSIZ];
  20. int uflag = 1;            /* default is union of -d and -u outputs */
  21. int dflag = 1;            /* flags are mutually exclusive */
  22. int cflag = 0;
  23. int fields = 0;
  24. int chars = 0;
  25.  
  26. FILE *xfopen(fn, mode)
  27. char *fn, *mode;
  28. {
  29.   FILE *p;
  30.   extern int errno;
  31.   extern char *sys_errlist[];
  32.  
  33.   if ((p = fopen(fn, mode)) == NULL) {
  34.     perror("uniq");
  35.     fflush(stdout);
  36.     exit(1);
  37.   }
  38.   return(p);
  39. }
  40.  
  41. main(argc, argv)
  42. char *argv[];
  43. {
  44.   char *p;
  45.   int inf = -1, outf;
  46.  
  47.   setbuf(stdout, buffer);
  48.   for (--argc, ++argv; argc > 0 && (**argv == '-' || **argv == '+');
  49.        --argc, ++argv) {
  50.     if (**argv == '+')
  51.         chars = atoi(*argv + 1);
  52.     else if (isdigit(argv[0][1]))
  53.         fields = atoi(*argv + 1);
  54.     else if (argv[0][1] == '\0')
  55.         inf = 0;    /* - is stdin */
  56.     else
  57.         for (p = *argv + 1; *p; p++) {
  58.             switch (*p) {
  59.                 case 'd':
  60.                 dflag = 1;
  61.                 uflag = 0;
  62.                 break;
  63.                 case 'u':
  64.                 uflag = 1;
  65.                 dflag = 0;
  66.                 break;
  67.                 case 'c':    cflag = 1;    break;
  68.                 default:    usage();
  69.             }
  70.         }
  71.   }
  72.  
  73.   /* Input file */
  74.   if (argc == 0)
  75.     inf = 0;
  76.   else if (inf == -1) {        /* if - was not given */
  77.     fclose(stdin);
  78.     xfopen(*argv++, "r");
  79.     argc--;
  80.   }
  81.   if (argc == 0)
  82.     outf = 1;
  83.   else {
  84.     fclose(stdout);
  85.     xfopen(*argv++, "w");
  86.     argc--;
  87.   }
  88.  
  89.   uniq();
  90.   fflush(stdout);
  91.   exit(0);
  92. }
  93.  
  94. char *skip(s)
  95. char *s;
  96. {
  97.   int n;
  98.  
  99.   /* Skip fields */
  100.   for (n = fields; n > 0; --n) {
  101.     /* Skip blanks */
  102.     while (*s && (*s == ' ' || *s == '\t')) s++;
  103.     if (!*s) return s;
  104.     while (*s && (*s != ' ' && *s != '\t')) s++;
  105.     if (!*s) return s;
  106.   }
  107.  
  108.   /* Skip characters */
  109.   for (n = chars; n > 0; --n) {
  110.     if (!*s) return s;
  111.     s++;
  112.   }
  113.   return s;
  114. }
  115.  
  116. int equal(s1, s2)
  117. char *s1, *s2;
  118. {
  119.   return !strcmp(skip(s1), skip(s2));
  120. }
  121.  
  122.  
  123. show(line, count)
  124. char *line;
  125. {
  126.   if (cflag)
  127.     printf("%4d %s", count, line);
  128.   else {
  129.     if ((uflag && count == 1) || (dflag && count != 1))
  130.         printf("%s", line);
  131.   }
  132. }
  133.  
  134. /* The meat of the whole affair */
  135. char *nowline, *prevline, buf1[1024], buf2[1024];
  136.  
  137. uniq()
  138. {
  139.   char *p;
  140.   int seen;
  141.  
  142.   /* Setup */
  143.   prevline = buf1;
  144.   if (getline(prevline, 1024) < 0) return(0);
  145.   seen = 1;
  146.   nowline = buf2;
  147.  
  148.   /* Get nowline and compare if not equal, dump prevline and swap
  149.    * pointers else continue, bumping seen count */
  150.   while (getline(nowline, 1024) > 0) {
  151.     if (!equal(prevline, nowline)) {
  152.         show(prevline, seen);
  153.         seen = 1;
  154.         p = nowline;
  155.         nowline = prevline;
  156.         prevline = p;
  157.     } else
  158.         seen += 1;
  159.   }
  160.   show(prevline, seen);
  161.   return 0;
  162. }
  163.  
  164. usage()
  165. {
  166.   std_err("Usage: uniq [-udc] [+n] [-n] [input [output]]\n");
  167. }
  168.  
  169.  
  170. int getline(buf, count)
  171. char *buf;
  172. int count;
  173. {
  174.   int c;
  175.   int ct = 0;
  176.  
  177.   while (ct++ < count) {
  178.     c = getc(stdin);
  179.     if (c < 0) return(-1);
  180.     *buf++ = c;
  181.     if (c == '\n') {
  182.         *buf++ = 0;
  183.         return(ct);
  184.     }
  185.   }
  186.   return(ct);
  187. }
  188.